package tr.edu.ege.kipler.syntax;

/**
 * 
 * @author İnanç Seylan
 *
 */
public class ModalExpression implements WorldElement {

	/**
	 * The modal operator in this formula
	 */
	private ModalOperator operator;

	/**
	 * The formula that this agent believes/intends, etc.
	 */
	private WorldElement expression;

	/**
	 * Default constructor
	 * 
	 */
	public ModalExpression() {
	}

	/**
	 * Constructor to initialize all the fields of this class by the given ones.
	 * 
	 * @param operator
	 *            The modal operator
	 * @param agent
	 *            The name of the agent
	 * @param formula
	 *            The formula
	 */
	public ModalExpression(ModalOperator operator, WorldElement formula) {
		setOperator(operator);
		setExpression(formula);
	}

	/**
	 * 
	 * @return the modal operator in this formula.
	 */
	public ModalOperator getOperator() {
		return operator;
	}

	/**
	 * Sets the modal operator of this formula.
	 * 
	 * @param operator
	 *            The modal operator
	 */
	public void setOperator(ModalOperator operator) {
		this.operator = operator;
	}

	public void setNegated(boolean negated) {
		if (negated == true) {
			setOperator(getOperator().getDual());
			getExpression().toggleNegated();
		}
	}

	public WorldElement toggleNegated() {
		setNegated(true);
		return this;
	}

	public boolean isNegated() {
		return false;
	}

	/**
	 * Returns true if obj is a modal formula whose operator, agent and formula
	 * is equal to this one's.
	 * 
	 * @see tr.edu.ege.seagent.alcbi.syntax.Formula#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (obj != null && (obj.getClass().equals(this.getClass()))) {
			ModalExpression other = (ModalExpression) obj;
			return (this.isNegated() == other.isNegated()
					&& this.getOperator().equals(other.getOperator()) && this
					.getExpression().equals(other.getExpression()));
		}
		return false;
	}

	/**
	 * This must be overridden when equals is overridden.
	 * 
	 * @return hash code of this formula.
	 */
	@Override
	public int hashCode() {
		return 17 * 37 + new Boolean(isNegated()).hashCode()
				+ getOperator().hashCode() + getExpression().hashCode();
	}

	public ModalExpression copy() {
		ModalExpression mf = new ModalExpression();
		mf.setOperator(getOperator().copy());
		mf.setExpression(getExpression().copy());
		return mf;
	}

	public void accept(WorldElementVisitor v) {
		v.visitModalElement(this);
	}

	public WorldElement getExpression() {
		return expression;
	}

	public void setExpression(WorldElement expression) {
		this.expression = expression;
	}

	/**
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		StringBuffer buffer = new StringBuffer();
		buffer.append(getOperator());
		buffer.append("(\"");
		// buffer.append(getAgent());
		buffer.append("\", ");
		buffer.append(getExpression());
		buffer.append(")");
		// no need for negation check
		return buffer.toString();
	}

}
